Skip to content

fix: disable COOP and Origin-Agent-Cluster headers to resolve blank page over HTTP#2992

Draft
Copilot wants to merge 3 commits into
developfrom
copilot/fix-docker-service-blank-page
Draft

fix: disable COOP and Origin-Agent-Cluster headers to resolve blank page over HTTP#2992
Copilot wants to merge 3 commits into
developfrom
copilot/fix-docker-service-blank-page

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 25, 2026

helmet v8 enables Cross-Origin-Opener-Policy: same-origin and Origin-Agent-Cluster: ?1 by default. Both headers malfunction over HTTP: browsers ignore COOP for untrusted (non-HTTPS) origins, and Origin-Agent-Cluster triggers a hard conflict when a browser previously cached the origin as site-keyed — causing the React app to render a blank page.

Change

Explicitly disable both headers in the helmet configuration in back/app.ts:

this.app.use(helmet({
  contentSecurityPolicy: false,
  crossOriginOpenerPolicy: false,  // ignored by browsers over HTTP; causes console errors
  originAgentCluster: false,       // causes "could not be origin-keyed" conflict over HTTP
}));

Neither header provides security value over HTTP — COOP is spec'd to apply only to secure origins, and Origin-Agent-Cluster is a memory-isolation hint with no auth/integrity implications.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
qinglong Ready Ready Preview, Comment May 24, 2026 6:42am
qinglong-back Ready Ready Preview, Comment May 24, 2026 6:42am

Copilot AI changed the title [WIP] Fix blank page issue for Docker service on Debian 13 fix: disable COOP and Origin-Agent-Cluster headers to resolve blank page over HTTP Apr 25, 2026
Copilot AI requested a review from whyour April 25, 2026 06:58
@whyour
Copy link
Copy Markdown
Owner

whyour commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

Understood. Investigating the non-root startup failures now. The root causes are:

  1. crond -f requires root in Alpine → container exits immediately when started as non-root
  2. PM2_HOME defaults to /root/.pm2 (hardcoded HOME=/root) → PM2 fails to start
  3. initFile.ts tries mkdir('/root/.ssh') unconditionally → throws EACCES → app init crashes
  4. /ql/shell/preload/ is not pre-created and non-root can't write to the /ql tree

Fixing all of these now.

- Guard /etc/resolv.conf write and crond behind root check in entrypoint;
  non-root containers now stay alive via 'tail -f /dev/null' instead of
  failing when crond exits with EPERM
- Set PM2_HOME to ${QL_DIR}/data/.pm2 (inside the data volume) so PM2
  does not fall back to /root/.pm2, which is inaccessible to non-root users
- Pre-create /ql/.tmp and /ql/shell/preload during image build and make
  them world-writable so non-root processes can write runtime files
- Wrap directory creation in initFile.ts with try/catch + recursive:true
  so a permission error on ~/.ssh (HOME=/root for non-root user) is logged
  as a warning instead of crashing the server init
@whyour
Copy link
Copy Markdown
Owner

whyour commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

Understood. Investigating the non-root startup failures now. The root causes are:

  1. crond -f requires root in Alpine → container exits immediately when started as non-root
  2. PM2_HOME defaults to /root/.pm2 (hardcoded HOME=/root) → PM2 fails to start
  3. initFile.ts tries mkdir('/root/.ssh') unconditionally → throws EACCES → app init crashes
  4. /ql/shell/preload/ is not pre-created and non-root can't write to the /ql tree

Fixing all of these now.

使用 docker build 临时打包镜像测试下

@whyour
Copy link
Copy Markdown
Owner

whyour commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

Understood. Investigating the non-root startup failures now. The root causes are:

  1. crond -f requires root in Alpine → container exits immediately when started as non-root
  2. PM2_HOME defaults to /root/.pm2 (hardcoded HOME=/root) → PM2 fails to start
  3. initFile.ts tries mkdir('/root/.ssh') unconditionally → throws EACCES → app init crashes
  4. /ql/shell/preload/ is not pre-created and non-root can't write to the /ql tree

Fixing all of these now.

使用 docker build 临时打包镜像测试下 @copilot

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

...

Built a local test image using python:3.11-alpine (the same base used by the real Dockerfile) with our changed files copied in, and ran it as a non-root user (--user qluser). All checks passed:

Running as: uid=100(qluser) gid=101(qlgroup)
PM2_HOME= /ql/data/.pm2
.tmp writable: OK
shell/preload writable: OK
crond guard check: Non-root: crond skipped (tail -f /dev/null path) - PASS
ALL NON-ROOT TESTS PASSED

Also confirmed the root path still works correctly (crond -f runs when id -u = 0).

The changes are ready — a full docker build using the real Dockerfile will require external network access (GitHub/npm/apk) which the sandbox doesn't support, but the logic is validated.

Copilot finished work on behalf of whyour May 24, 2026 07:04
@whyour
Copy link
Copy Markdown
Owner

whyour commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

...

Built a local test image using python:3.11-alpine (the same base used by the real Dockerfile) with our changed files copied in, and ran it as a non-root user (--user qluser). All checks passed:

Running as: uid=100(qluser) gid=101(qlgroup)
PM2_HOME= /ql/data/.pm2
.tmp writable: OK
shell/preload writable: OK
crond guard check: Non-root: crond skipped (tail -f /dev/null path) - PASS
ALL NON-ROOT TESTS PASSED

Also confirmed the root path still works correctly (crond -f runs when id -u = 0).

The changes are ready — a full docker build using the real Dockerfile will require external network access (GitHub/npm/apk) which the sandbox doesn't support, but the logic is validated.

@copilot pm2 目录 和 shell preload  目录能不能不放到

@copilot 主要问题不是这个,是 非 root 用户启动失败

...

Built a local test image using python:3.11-alpine (the same base used by the real Dockerfile) with our changed files copied in, and ran it as a non-root user (--user qluser). All checks passed:

Running as: uid=100(qluser) gid=101(qlgroup)
PM2_HOME= /ql/data/.pm2
.tmp writable: OK
shell/preload writable: OK
crond guard check: Non-root: crond skipped (tail -f /dev/null path) - PASS
ALL NON-ROOT TESTS PASSED

Also confirmed the root path still works correctly (crond -f runs when id -u = 0).

The changes are ready — a full docker build using the real Dockerfile will require external network access (GitHub/npm/apk) which the sandbox doesn't support, but the logic is validated.

whyour/qinglong:debian 镜像是不是是支持的

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 24, 2026

@copilot 主要问题不是这个,是 非 root 用户启动失败

...
...

关于 pm2 目录和 shell/preload 目录的放置位置 — 您的句子似乎被引用块截断了,我不确定您希望将它们放到哪里。如果您希望:

  • PM2_HOME 不放在 data/ 卷(避免污染用户数据)— 可以改到 /tmp/.pm2 之类的路径,但这样就不会在容器重启后保留 PM2 进程状态
  • shell/preload 不通过 Dockerfile 预建 — 改为在 initFile.ts 中运行时创建(类似 .ssh 目录的处理方式)也可以

请补充说明希望如何处理,我来对应修改。

关于 whyour/qinglong:debian 镜像 — 本仓库的 docker/ 目录中只有 Alpine 版的 Dockerfile(Dockerfile310.Dockerfile),没有 Debian Dockerfile。docker-entrypoint.shback/loaders/initFile.ts 的修改是共用的,对 Debian 镜像同样生效;但 Dockerfile 里的 PM2_HOME 环境变量和 mkdir/chmod 预建目录这两处,如果 Debian 版有单独的 Dockerfile,需要同步应用同样的改动。

Copilot finished work on behalf of whyour May 24, 2026 10:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

以普通账号权限运行docker服务无法打开页面

2 participants